﻿using System;
using System.IO;
using System.Collections.Generic;
using Microsoft.Data.Schema.ScriptDom.Sql;
using System.Linq;
using System.Text;

namespace Neznayka
{
    internal class UpdatedVariableVisitor : TSqlConcreteFragmentVisitor
    {
        private List<SQLExpressionDependency> _targets;

        #region ctor
        public UpdatedVariableVisitor()
        {
            _targets = new List<SQLExpressionDependency>();
        }
        #endregion

        #region properties
        public List<SQLExpressionDependency> SetVariables
        {
            get  {  return _targets;  }
        }
        #endregion

        #region overrides
        public override void ExplicitVisit(ExecuteParameter node)
        {
            if (node.IsOutput == true)
            {
                Literal PV = node.ParameterValue as Microsoft.Data.Schema.ScriptDom.Sql.Literal;
                if (PV != null && PV.LiteralType == LiteralType.Variable)
                {
                    SQLExpressionDependency ed = new SQLExpressionDependency((Literal)(node.ParameterValue));
                    // there are no dependencies in the sense we are using them.
                    _targets.Add(ed);
                }
            }

        }
        public override void ExplicitVisit(SetVariableStatement node)
        {
            if (node.VariableName != null && node.VariableName.LiteralType == LiteralType.Variable)
            {
                SQLExpressionDependency ed = new SQLExpressionDependency(node.VariableName);
                // NOOOO not here
                //// If it's a self-referencing assignment, throw target into dependencies too.
                //if (node.AssignmentKind != AssignmentKind.Equals)
                //{
                //    ed.addDependency(node.VariableName);
                //}

                //Get variable references in the expression.
                VariableUsageVisitor usageVisitor = new VariableUsageVisitor();
                node.Expression.Accept(usageVisitor);
                List<Literal> variableReferences = usageVisitor.VariableReferences;
                //Add to dependencies
                ed.addDependencies(variableReferences);
                _targets.Add(ed);
            }
        }
        public override void ExplicitVisit(SelectSetVariable node)
        {
            if (node.VariableName != null && node.VariableName.LiteralType == LiteralType.Variable)
            {
                SQLExpressionDependency ed = new SQLExpressionDependency(node.VariableName);
                // NOOOO not here
                //// If it's a self-referencing assignment, throw target into dependencies too.
                //if (node.AssignmentKind != AssignmentKind.Equals)
                //{
                //    ed.addDependency(node.VariableName);
                //}

                //Get variable references in the expression.
                VariableUsageVisitor usageVisitor = new VariableUsageVisitor();
                node.Expression.Accept(usageVisitor);
                List<Literal> variableReferences = usageVisitor.VariableReferences;
                //Add to dependencies
                ed.addDependencies(variableReferences);
                _targets.Add(ed);
            }
        }
        // This override prevents us writing a vistor for ExecuteParameter
        // The default visitor action stops.
        public override void ExplicitVisit(ExecuteStatement node)
        {
//            if (node.Variable != null && node.Variable.LiteralType == LiteralType.Variable && node.Variable.Value != "")
              if (node.Variable != null && node.Variable.LiteralType == LiteralType.Variable && ! String.IsNullOrEmpty(node.Variable.Value))
                {
                SQLExpressionDependency ed = new SQLExpressionDependency(node.Variable);
                // there are no dependencies in the sense we are using them.
                _targets.Add(ed);
            }
            // recurse into parameters
            node.AcceptChildren(this);
        }

        public override void ExplicitVisit(AssignmentSetClause node)
        {
            if (node.Variable != null && node.Variable.LiteralType == LiteralType.Variable)
            {
                SQLExpressionDependency ed = new SQLExpressionDependency(node.Variable);
                // NOOOO not here
                //// If it's a self-referencing assignment, throw target into dependencies too.
                //if (node.AssignmentKind != AssignmentKind.Equals)
                //{
                //    ed.addDependency(node.VariableName);
                //}

                //Get variable references in the expression.
                VariableUsageVisitor usageVisitor = new VariableUsageVisitor();
                node.NewValue.Accept(usageVisitor);
                List<Literal> variableReferences = usageVisitor.VariableReferences;
                //Add to dependencies
                ed.addDependencies(variableReferences);
                _targets.Add(ed);
            }
        }
        public override void ExplicitVisit(BeginDialogStatement node)
        {
            if (node.Handle != null && node.Handle.LiteralType == LiteralType.Variable)
            {
                SQLExpressionDependency ed = new SQLExpressionDependency(node.Handle);
                _targets.Add(ed);
            }
        }
        public override void ExplicitVisit(ReceiveStatement node)
        {
            if (node.SelectElements != null)
            {
                foreach (var v in node.SelectElements)
                {
                    SelectSetVariable ssv = v as SelectSetVariable;
                    if (ssv != null)
                    {
                        SQLExpressionDependency ed = new SQLExpressionDependency(ssv.VariableName);
                        _targets.Add(ed);
                    }
                }
            }
        }

        #endregion

    }
}

